package cn.com.infcn.monitor.client;

import java.net.InetSocketAddress;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.infcn.monitor.bean.IFCRequestBean;
import cn.com.infcn.monitor.bean.IFCResponseBean;


public class MonitorClient extends IoHandlerAdapter {
	
	private final Logger logger = LoggerFactory.getLogger(MonitorClient.class);
	public static final int CONNECT_TIMEOUT = 3000;
	
	private String host;
    private int port;
    private SocketConnector connector;
    private IoSession session;
    private ResponseListener listener;
    
    public MonitorClient(ResponseListener listener) {
    	this.listener = listener;
    	

        connector = new NioSocketConnector();
//        connector.getFilterChain().addLast("compression", new CompressionFilter(CompressionFilter.COMPRESSION_MAX));
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(  
                new ObjectSerializationCodecFactory()));
        connector.setHandler(this);
    }
    
    public boolean isConnected() {
        return (session != null && session.isConnected());
    }

    public void connect() {
        connect(host, port);
    }

    public void connect(String host, int port) {
        this.host = host;
        this.port = port;

        ConnectFuture connectFuture = connector.connect(new InetSocketAddress(this.host, this.port));
        connectFuture.awaitUninterruptibly(CONNECT_TIMEOUT);
        try {
            session = connectFuture.getSession();
        }
        catch (RuntimeIoException e) {
        	logger.warn("connect gateway failed");
            listener.onExceptionCaught(e);
        }
    }
    
    public void sendRequest(IFCRequestBean requestBean) {
    	if (session != null) {
    		session.write(requestBean).awaitUninterruptibly();
        }
    	else {
            listener.onExceptionCaught(new Throwable("not connected"));
        }
    }
    
    public void disconnect() {
        if (session != null) {
            session.close(true).awaitUninterruptibly(CONNECT_TIMEOUT);
            session = null;
        }
    }

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		logger.debug("messageReceived: {}", message);
		listener.messageReceived((IFCResponseBean)message);
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		logger.debug("sessionClosed");
		listener.sessionClosed();
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		logger.debug("sessionOpened");
		listener.sessionOpened();
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		logger.error(cause.getMessage());
		
		listener.onExceptionCaught(cause);
	}

}
